const AStarTask = function (exports) {
	class Node{
		constructor(x,y) {
			this.x = x;
			this.y = y;
	
			this.g = 0;
			this.h = 0;
			this.f = 0;
			this.parent = null;
		}
		initF(endNode){
			let g0 = this.getG(this, this.parent);
			this.g = this.parent.g + g0;
			//对角距离
			let dx = Math.abs(this.x - endNode.x);
			let dy = Math.abs(this.y - endNode.y);
			let maxD = Math.max(dx, dy);
			let minD = Math.min(dx, dy);
			this.h = Math.SQRT2 * minD + (maxD - minD);
			// this.h = Math.sqrt(dx*dx + dy*dy);
			this.f = this.g + this.h;
		}
		getG(n1, n2){
			let g0 = Math.SQRT2;
			if(n1.x === n2.x || n1.y === n2.y){
				g0 = 1;
			}
			return g0;
		}
		equals(node){
			if(node.x === this.x && node.y === this.y){
				return true;
			}
			return false;
		}
	}
	class Task{
		constructor() {
			this.pathSet = [];
			this.startNode = null;
			this.endNode = null;
			this.openSet = [];
			this.closeSet = [];
			this.wallSet = [];
			this.setSide();
		}
		setStart(x, y){
			this.startNode = new Node(x, y);
		}
		setEnd(x, y){
			this.endNode = new Node(x, y);
		}
		setWallFromArray(array){
			this.wallSet = [];
			for(let i=0; i<array.length; i+=2){
				this.wallSet.push(new Node(array[i], array[i+1]));
			}
		}
		addWall(x, y){
			let node = new Node(x, y);
			if(!this.findNode(this.wallSet, node)){
				this.wallSet.push(node);
			}
		}
		reSet(){
			this.pathSet = [];
			this.startNode = null;
			this.endNode = null;
			this.openSet = [];
			this.closeSet = [];
			this.wallSet = [];
		}
		setSide(minx=-40,miny=-40,maxx=200,maxy=200){
			this.side={	minx:minx,miny:miny,maxx:maxx,maxy:maxy}
		}
		findPath(){
			let dtime=new Date().getTime();
			this.pathSet = [];
			this.closeSet = [];
			if(!this.startNode){
				console.log('未设置起点');
				return;
			}
			if(!this.endNode){
				console.log('未设置终点');
				return;
			}
			if(this.findNode(this.wallSet, this.endNode)){
				console.log('终点在墙里！');
				return;
			}
			this.openSet = [this.startNode];
			while(this.openSet.length>0){
				this.openSet.sort(this.sortNode);
				let n = this.openSet[0];
				this.removeNode(this.openSet, n);
				this.addNode(this.closeSet, n);
				if(n.equals(this.endNode)){
					//找到终点
					let cur = n;
					while(cur.parent){
						this.pathSet.unshift(cur);
						cur = cur.parent;
					}
					//console.log(this.pathSet);
					break;
				}
				for(let x=n.x-1; x<=n.x+1; x++){
					for(let y=n.y-1; y<=n.y+1; y++){
						let m = new Node(x,y);
						if(m.equals(n) || this.findNode(this.wallSet, m) || this.findNode(this.closeSet, m)){
							continue;
						}
						if(this.findNode(this.openSet, m)){
							let newG = n.g + n.getG(m,n);
							if(newG<m.g){
								m.g = newG;
								m.f = m.g + m.h;
								m.parent = n;
							}
						}else{
							m.parent = n;
							m.initF(this.endNode);
							this.addNode(this.openSet, m);
						}
					}
				}
				let s=this.side;
				if(n.x<s.minx||n.y<s.miny||n.x>s.maxx||n.y>s.maxy){
					console.log('超出地图范围');
					this.pathSet.length=0;
					break;
				}
				//console.log(n.x,n.y)
			}
			if(this.pathSet.length === 0){
				console.log('无法找到路径');
			}
			console.log(`查找路径耗时：${new Date().getTime()-dtime}ms`)
		}
		sortNode(a, b) {
			return a.f - b.f;
		}
		removeNode(set, node){
			for(let i=0; i<set.length; i++){
				if(set[i].x === node.x && set[i].y === node.y){
					let n = set[i];
					set.splice(i,1);
					return n;
				}
			}
		}
		addNode(set, node){
			set.push(node);
		}
		findNode(set, node){
			for(let i=0; i<set.length; i++){
				if(set[i].x === node.x && set[i].y === node.y){
					return true;
				}
			}
			return false;
		}
	}
	exports.Node = Node;
	exports.Task = Task;
    Object.defineProperty(exports, "__esModule", {
        value: true
    });
    return exports
}
({});
